package cn.kgc.config;

import cn.kgc.service.IndustryService;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author YC
 */
@Configuration
//@EnableScheduling 当前模块引入了RabbitMQ模块，已经引入了定时任务
public class IndustryBloomFillerConfig {

    @Resource
    private RedissonClient redissonClient;
    @Resource
    private IndustryService industryService;

    @Bean
    public RBloomFilter<String> industryBloomFiller() {
        RBloomFilter<String> industryBloomFiller = redissonClient.getBloomFilter("industryBloomFiller");
        // 布隆过滤器的容量和误判率
        industryBloomFiller.tryInit(10000, 0.01);
        return industryBloomFiller;
    }

    /**
     * 定时任务，在业务的低峰期重建布隆过滤器（布隆过滤器因其保存存在痕迹的原理无法删除某个数据的存在痕迹，需要重新构建）
     * 注解@Scheduled(cron = "0 0 3 * * ?")用于定时任务调度按照时间规则执行
     * (秒 分 时 日 月 星期) *表示任意 ?表示不指定（因为已经指定了日）
     */
    @Scheduled(cron = "0 0 3 * * ?")
    public void rebuildIndustryBloomFiller() {
        // 查询出所有一级行业分类ID（一定不要造成OOM内存溢出,不要一次从表中查询出海量数据）
        List<String> topIndustryId = industryService.getTopIndustryId();
        // 创建新的布隆过滤器
        RBloomFilter<String> industryBloomFiller = redissonClient.getBloomFilter("new_industryBloomFiller");
        industryBloomFiller.tryInit(1000, 0.01);
        topIndustryId.forEach(industryBloomFiller::add);
        // 替换旧的布隆过滤器（原子切换过滤器）
//        redissonClient.getBucket("industryBloomFiller").compareAndSet(industryBloomFiller, industryBloomFiller);
        redissonClient.getKeys().rename("new_industryBloomFiller", "industryBloomFiller");
    }

}
